package com.dengyafei.service.impl;

import com.dengyafei.bean.*;
import com.dengyafei.constant.RecommendConstant;
import com.dengyafei.mapper.ItemEntityMapper;
import com.dengyafei.mapper.PositionEntityMapper;
import com.dengyafei.mapper.RelateEntityMapper;
import com.dengyafei.mapper.UserEntityMapper;
import com.dengyafei.service.RecommendService;
import com.dengyafei.utils.TypeParseUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.mahout.cf.taste.impl.neighborhood.NearestNUserNeighborhood;
import org.apache.mahout.cf.taste.impl.recommender.GenericItemBasedRecommender;
import org.apache.mahout.cf.taste.impl.recommender.GenericUserBasedRecommender;
import org.apache.mahout.cf.taste.impl.similarity.PearsonCorrelationSimilarity;
import org.apache.mahout.cf.taste.model.DataModel;
import org.apache.mahout.cf.taste.neighborhood.UserNeighborhood;
import org.apache.mahout.cf.taste.recommender.RecommendedItem;
import org.apache.mahout.cf.taste.recommender.Recommender;
import org.apache.mahout.cf.taste.similarity.ItemSimilarity;
import org.apache.mahout.cf.taste.similarity.UserSimilarity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 邓亚非
 */
@Service
@Slf4j
public class RecommendServiceImpl implements RecommendService {

    @Autowired
    UserEntityMapper userEntityMapper;

    @Autowired
    ItemEntityMapper itemEntityMapper;

    @Autowired
    RelateEntityMapper relateEntityMapper;

    @Autowired
    DataModel dataModel;

    @Autowired
    PositionEntityMapper positionEntityMapper;
    /**
     * 查询所有的users
     *
     * @return
     */
    @Override
    public List<UserEntity> findUserEntity() {
        return userEntityMapper.findAllUser();
    }

    /**
     * 查询所有的items
     *
     * @return
     */
    @Override
    public List<ItemEntity> findItemEntity() {
        return itemEntityMapper.findAllItem();
    }

    /**
     * 查询所有的relates
     *
     * @return
     */
    @Override
    public List<RelateEntity> findRelateEntity() {
        return relateEntityMapper.findAllRelateEntity();
    }

    /**
     * 生成最终的推荐列表:猜你喜欢
     *
     * @param id
     * @return
     */
    @Override
    public List<ItemEntity> recommendList(Integer id) {

       return null;
    }

    /**
     * 基于用户的协同过滤推荐算法
     * @param userId
     * @param howMany
     * @return
     */
    @Override
    public List<PositionEntity> getRecommendItemByUser(Long userId, int howMany) {
        List<PositionEntity> items=null;
        try {
//            计算相似度
            UserSimilarity userSimilarity = new PearsonCorrelationSimilarity(dataModel);
//            计算最近领域基于用户的协同过滤算法推荐
            UserNeighborhood userNeighborhood=new NearestNUserNeighborhood(100,userSimilarity,dataModel);
//            构造推荐器,基于用户的协同过滤推荐
            Recommender recommender=new GenericUserBasedRecommender(dataModel,userNeighborhood,userSimilarity);
            Long start=System.currentTimeMillis();
//            推荐商品
            List<RecommendedItem> recommendedItems=recommender.recommend(userId,howMany);
            List<Long> itemIds=new ArrayList<>();
            for (RecommendedItem recommendedItem:recommendedItems){
                itemIds.add(recommendedItem.getItemID());
            }
            System.out.println("商品id集合:"+itemIds);
//          根据商品id查询商品
            if (itemIds!=null&&itemIds.size()>0){
                List<Integer> list = TypeParseUtil.longParseIntegers(itemIds);
                items=positionEntityMapper.findAllByIds(list);
            }else {
                items=new ArrayList<>();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        log.info("items:{}",items.size());
//        使用代码层面解决冷启动问题
        if (CollectionUtils.isEmpty(items)){
            List<PositionEntity> positionEntities = positionEntityMapper.recommendPositions();
            List<PositionEntity> position = positionEntities.subList(0, RecommendConstant.RECOMMEND_NUMBERS);
            return position;
        }else if (items.size()< RecommendConstant.RECOMMEND_NUMBERS){
            List<PositionEntity> positionEntities = positionEntityMapper.recommendPositions();
            return TypeParseUtil.setParseList(items,positionEntities);
        }
       log.info("items:{}",items.size());
        return items;
    }

    /**
     * 基于岗位的协同过滤推荐算法
     * @param userId
     * @param itemId
     * @param howMany
     * @return
     */
    @Override
    public List<PositionEntity> getRecommendItemByItem(Long userId, Long itemId, int howMany) {
        List<PositionEntity> items=null;
        try {
//            计算相似度
            ItemSimilarity itemSimilarity=new PearsonCorrelationSimilarity(dataModel);
//            构建推荐器
            GenericItemBasedRecommender recommender=new GenericItemBasedRecommender(dataModel,itemSimilarity);
            Long start=System.currentTimeMillis();
//            物品推荐相似度
            List<RecommendedItem> recommendedItems=recommender.recommendedBecause(userId,itemId,howMany);
//            推荐结果
            List<Long> itemIds=new ArrayList<>();
            for (RecommendedItem recommendedItem:recommendedItems){
                itemIds.add(recommendedItem.getItemID());
            }
//            根据商品id查询商品信息
            if (itemIds!=null&&itemIds.size()>0){
                List<Integer> list = TypeParseUtil.longParseIntegers(itemIds);
                items=positionEntityMapper.findAllByIds(list);
            }else {
                items=new ArrayList<>();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (CollectionUtils.isEmpty(items)){
            return positionEntityMapper.recommendPositions().subList(0,RecommendConstant.RECOMMEND_NUMBERS);
        }else if(items.size()<RecommendConstant.RECOMMEND_NUMBERS){
            List<PositionEntity> positionEntities = positionEntityMapper.recommendPositions();
            return TypeParseUtil.setParseList(items,positionEntities);
        }
        return items;
    }
}